/*
********************************************************************************
* Copyright (C) 2021, xiang.D <dx_65535@163.com>.
* All right reserved.
*
* File Name   : singleton.cc
* Author      :
* Version     : V1.0
* Description :
* Journal     : 2021-10-20 init v1.0
* Brief       : Blog: https://blog.csdn.net/qq_38750572?spm=1001.2014.3001.5343
* Others      :
                Compile command: g++ -Wl,--no-as-needed -std=c++11 -pthread simpleSingleton.cc
********************************************************************************
*/
#include <iostream>
#include <unistd.h>
#include <thread>
#include <mutex>

using namespace std;

#define MUTEX_SWITCH 1

class CSingleton
{
public:

    static CSingleton* getInstance(const string& value);

    string getValue()
    {
        return mValue;
    }

private:

    CSingleton(const string value): mValue(value)
    {

    }

    ~CSingleton() {}

    string mValue;
	static CSingleton *mInstance;
#if MUTEX_SWITCH
    static mutex mMutex;
#endif
};

CSingleton* CSingleton::mInstance(nullptr);

#if MUTEX_SWITCH
mutex CSingleton::mMutex;
#endif

CSingleton* CSingleton::getInstance(const string& value)
{

#if MUTEX_SWITCH
    std::lock_guard<std::mutex> lock(mMutex);
#endif
    if (nullptr == mInstance) {
        cout << "Open mutex" << "\n";
        mInstance = new CSingleton(value);
    }
    return mInstance;
}

void threadFirst()
{
    sleep(2);
    CSingleton* pSingleton = CSingleton::getInstance("first");
    cout << pSingleton->getValue() << "\n";
}

void threadSecond()
{
    sleep(2);
    CSingleton* pSingleton = CSingleton::getInstance("second");
    cout << pSingleton->getValue() << "\n";
}

void threadThird()
{
    sleep(2);
    CSingleton* pSingleton = CSingleton::getInstance("third");
    cout << pSingleton->getValue() << "\n";
}

int main(int argc, char *argv[])
{
    thread t1(threadFirst);
    thread t2(threadSecond);
    thread t3(threadThird);
    t1.join();
    t2.join();
    t3.join();

    return 0;
}

